import { IScope } from '../types';
import { Scope } from './Scope';
import { reactNodeGenerator } from './jsx';
import { extractDollarStrings } from '@/types/modules/editor/server/code-transformer/utils/extractDollarStrings';
import { generateDataInterface } from '@/types/modules/editor/server/code-transformer/utils/export/generateTsType';
import { DependenciesTransformer } from '../utils/deps';
import { DocFrameType, LcDocument } from '@/types/modules/editor/types/editor.type';
import { getDocumentPath } from '@/types/modules/editor/server/virtual-file-system/utils/source-path';
import codeFormatter from '@/utils/editor-adapter/code-formatter';

/**
 * 处理 state 对象中的 JSExpression
 */
function processStateValue(value: any): string {
  if (!value || typeof value !== 'object') {
    return JSON.stringify(value);
  }

  if (Array.isArray(value)) {
    const arrayItems = value.map((item) => processStateValue(item));
    return `[${arrayItems.join(', ')}]`;
  }

  if (value.type === 'JSExpression') {
    return value.value;
  }

  const entries = Object.entries(value);
  const processedEntries = entries.map(([key, val]) => {
    return `${JSON.stringify(key)}: ${processStateValue(val)}`;
  });

  return `{${processedEntries.join(', ')}}`;
}

/**
 * 生成 LcDocument 元数据注释 (JSDoc 格式)
 */
function generateDocumentMetaComment(doc: LcDocument): string {
  const lines = [`/**`];

  // 标题作为主描述
  if (doc.title) {
    lines.push(` * ${doc.title}`);
  }

  // 描述信息
  if (doc.description) {
    lines.push(` * ${doc.description}`);
  }

  // 只有当有描述时，才在描述和标签之间添加空行分隔
  const hasDescription = doc.description;
  const hasTags =
    doc.type ||
    doc.route?.path ||
    doc.width ||
    doc.height ||
    doc.backgroundColor ||
    (doc.frames && doc.frames.length > 0) ||
    (doc.clients && doc.clients.length > 0) ||
    doc.portal;

  if (hasDescription && hasTags) {
    lines.push(` *`);
  }

  // 文档类型
  if (doc.type) {
    lines.push(` * @type ${doc.type}`);
  }

  // 路由信息
  if (doc.route?.path) {
    lines.push(` * @route ${doc.route.path}`);
  }

  // 屏幕尺寸和背景色
  if (doc.width || doc.height || doc.backgroundColor) {
    let screenInfo = '';
    if (doc.width && doc.height) {
      screenInfo = `${doc.width}x${doc.height}`;
    } else if (doc.width) {
      screenInfo = `${doc.width}w`;
    } else if (doc.height) {
      screenInfo = `${doc.height}h`;
    }

    if (doc.backgroundColor) {
      screenInfo += screenInfo ? ` ${doc.backgroundColor}` : doc.backgroundColor;
    }

    if (screenInfo) {
      lines.push(` * @screen ${screenInfo}`);
    }
  }

  // 支持的框架
  if (doc.frames && doc.frames.length > 0) {
    lines.push(` * @frames ${doc.frames.join(', ')}`);
  }

  // 支持的客户端
  if (doc.clients && doc.clients.length > 0) {
    lines.push(` * @clients ${doc.clients.join(', ')}`);
  }

  // 穿梭组件标识
  if (doc.portal) {
    lines.push(` * @portal true`);
  }

  lines.push(` */`);
  return lines.join('\n');
}

/**
 * 生成文档代码.tsx文件
 */
export const generateDocumentCode = async function (
  sourceDoc: LcDocument,
  options: {
    path?: string;
    currentFrame?: DocFrameType;
    generateRender?: boolean;
  } = {},
) {
  const { path, generateRender = true, currentFrame = 'web' } = options;
  if (!sourceDoc) {
    throw new Error('文档不存在');
  }
  const filePath = path || getDocumentPath(sourceDoc).replace('.doc', '.tsx');
  const scope: IScope = Scope.createRootScope();

  const schemaStr = JSON.stringify(sourceDoc.schema);
  const parsedSchema = JSON.parse(schemaStr);
  // 生成Methods
  const actionTypes = sourceDoc.types?.filter((_) => _.type === 'action') || [];
  const methodCodes: string[] = [];
  for (const action of actionTypes) {
    const code = `${
      action.desc
        ? `/**
      * ${action.desc}
      */`
        : ''
    }
${action.source?.replace('function ', '') || ''}`;
    methodCodes.push(code);
  }
  const methodCode = '\n' + methodCodes.join('\n\n');
  // const methods = Object.assign(schema.lifeCycles || {}, schema.methods || {});
  // const methodCode = `${Object.keys(methods)
  //   .map((name) => {
  //     return methods[name].value.replace('function ', '');
  //   })
  //   .join('\n')}`;
  const refNames = extractDollarStrings(schemaStr);
  // console.log('refNames: ', refNames);
  scope.refNames = refNames;
  const jsx = reactNodeGenerator(parsedSchema, scope);
  const dataType = sourceDoc.types?.find((_) => _.type === 'data');
  let dataCode = '';
  if (dataType && dataType.fields && dataType.fields.length > 0) {
    dataCode = await generateDataInterface(dataType, {
      hasDefaultValue: false,
    });
  } else {
    // 如果没有数据类型，生成一个空的IState接口
    dataCode = 'class IState {}';
  }

  let propsCode = '';
  const props = (sourceDoc.componentMeta?.configure as any)?.props || [];
  if (props.length > 0) {
    const _propsCode = await generateDataInterface(
      {
        name: 'IProps',
        desc: 'props',
        type: 'props',
        fields: props,
      },
      {
        hasDefaultValue: false,
      },
    );
    try {
      propsCode = '\n' + _propsCode + '\n';
    } catch (e) {
      console.error(e);
    }
  } else {
    // 如果没有props，生成一个空的IProps接口
    propsCode = '\nclass IProps {}\n';
  }

  const importCode = await DependenciesTransformer.generateImportStatements(
    sourceDoc.componentsRoot?.[sourceDoc.frames?.find((_) => _ === currentFrame)] ||
      sourceDoc.componentsMap,
  );

  let code = `
class Document extends React.Component<IProps, IState> {${
    Object.keys(parsedSchema.defaultProps || {}).length
      ? `
  static defaultProps = ${JSON.stringify(parsedSchema.defaultProps)};`
      : ''
  }
  state = ${processStateValue(parsedSchema.state || {})}
  ${methodCode}

  render() {
    return (
      ${generateRender ? jsx : '{/* ... */}'}
    )
  }
}
`;
  try {
    code = await codeFormatter.format(code, 'react');
  } catch(e) {
    console.error(e);
  }
  const absCssFilePath = filePath.split('/').slice(-1)[0].replace('.tsx', '.css');

  // 生成文档元数据注释
  const metaComment = generateDocumentMetaComment(sourceDoc);

  if (dataCode) {
    code = `${metaComment}
import React from 'react';
${importCode}
${parsedSchema.css ? `import './${absCssFilePath}';` : ''}
${propsCode}
/*
 * 数据与接口请求定义
 */
${dataCode.replace('class data', 'class IState').replaceAll('  @DataSource', '\n  @DataSource')}

${code}
export default Document;`;
  } else {
    code = `${metaComment}
import React from 'react';
${importCode}
import './${absCssFilePath}';
${propsCode}
${code}
export default Document;`;
  }
  return code;
};
